package com.idea.relax.tool.core.annotation;

import com.idea.relax.tool.core.StringUtil;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.lang.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author: 沉香
 * @date: 2023/1/30
 * @description:
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ConditionalOnStringProperty.ConditionalOnPropertyStringCondition.class)
public @interface ConditionalOnStringProperty {

	String[] property();

	Condition condition() default Condition.EQ;

	String havingValue() default "";

	class ConditionalOnPropertyStringCondition extends SpringBootCondition {

		@Override
		public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
			Environment environment = context.getEnvironment();
			Map<String, Object> attrMap = metadata.getAnnotationAttributes(ConditionalOnStringProperty.class.getName());

			String[] property = (String[]) Objects.requireNonNull(attrMap).get("property");
			String havingValue = (String) Objects.requireNonNull(attrMap).get("havingValue");
			Condition condition = (Condition) Objects.requireNonNull(attrMap).get("condition");

			if (property == null || property.length == 0) {
				throw new IllegalStateException("values is not null!");
			}
			List<Boolean> booleans = new ArrayList<>();
			for (String prop : property) {
				String value = environment.getProperty(prop, "");
				if (Condition.EMPTY.equals(condition)) {
					if (StringUtil.eq(value, havingValue)) {
						booleans.add(true);
					}
				} else if (Condition.NOT_EMPTY.equals(condition)) {
					if (StringUtil.isNotBlank(value)) {
						booleans.add(true);
					}
				} else {
					if (StringUtil.eq(value, havingValue)) {
						booleans.add(true);
					}
				}
			}
			return booleans.size() == property.length ? ConditionOutcome.match() : ConditionOutcome.noMatch("");
		}
	}

}


